package com.zhz.common.tool.oss.aws;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.*;
import com.zhz.common.tool.oss.OssService;
import com.zhz.common.tool.oss.huaweicloud.VO.FileUploadStatusVO;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;

/**
 * 亚马逊上传服务
 *
 * @author zhouhengzhe
 */
public class AwsOssServiceImpl implements OssService {
    private final AmazonS3 s3client;


    public AwsOssServiceImpl(AwsOssProperties awsOssProperties) {
        checkAwsOssProperties(awsOssProperties);
        AwsClientBuilder.EndpointConfiguration endpointConfig =
                new AwsClientBuilder.EndpointConfiguration(awsOssProperties.getEndPoint()
                        , Region.getRegion(Regions.CN_NORTH_1).getName());

        AWSCredentials awsCredentials = new BasicAWSCredentials(awsOssProperties.getAccessKey(), awsOssProperties.getSecretKey());
        AWSCredentialsProvider awsCredentialsProvider = new AWSStaticCredentialsProvider(awsCredentials);
        ClientConfiguration clientConfig = new ClientConfiguration();
        clientConfig.setProtocol(Protocol.HTTP);
        this.s3client = AmazonS3Client.builder()
                .withEndpointConfiguration(endpointConfig)
                .withClientConfiguration(clientConfig)
                .withCredentials(awsCredentialsProvider)
                .disableChunkedEncoding()
                .withPathStyleAccessEnabled(true)
                .withForceGlobalBucketAccessEnabled(true)
                .build();
    }

    /**
     * 检查aws oss配置是否为空
     *
     * @param awsOssProperties aws oss配置
     */
    private void checkAwsOssProperties(AwsOssProperties awsOssProperties) {
        if (Objects.isNull(awsOssProperties)) {
            throw new RuntimeException("aws oss配置为空");
        }
        if (Objects.isNull(awsOssProperties.getAccessKey())) {
            throw new RuntimeException("aws oss配置accessKey为空");
        }
        if (Objects.isNull(awsOssProperties.getSecretKey())) {
            throw new RuntimeException("aws oss配置secretKey为空");
        }
        if (Objects.isNull(awsOssProperties.getEndPoint())) {
            throw new RuntimeException("aws oss配置endPoint为空");
        }
    }

    /**
     * 文件
     *
     * @param uploadFile 上传的文件
     * @param fileName   文件名称
     * @param bucketName 桶名称
     * @return
     */
    @Override
    public String uploadFile(MultipartFile uploadFile, String fileName, String bucketName) {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType(uploadFile.getContentType());
        objectMetadata.setContentLength(uploadFile.getSize());
        try {
            PutObjectResult putObjectResult = s3client.putObject(
                    new PutObjectRequest(bucketName,
                            fileName,
                            uploadFile.getInputStream(),
                            objectMetadata)
                            .withCannedAcl(CannedAccessControlList.PublicRead)
            );
            if (Objects.isNull(putObjectResult)) {
                throw new RuntimeException("文件上传失败");
            }
            //第一种方式
            return s3client.getUrl(bucketName, fileName).toString();
            //第二种方式，自己拼接
//                    awsOssProperties.getEndPoint() +
//                    bucketName +
//                    StrPoolUtils.SLASH +
//                    fileName;
        } catch (Exception e) {
            throw new RuntimeException("文件上传失败");
        }
    }

    /**
     * 上次文件流
     *
     * @param fileName   文件名称
     * @param bucketName 桶名称
     * @param out        文件流
     * @return
     */
    @Override
    public String uploadFileByte(String fileName, String bucketName, byte[] out, String contentType) {
        ByteArrayInputStream bis = new ByteArrayInputStream(out);
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(contentType);
        metadata.setContentLength(bis.available());

        PutObjectRequest putObjectRequest = new PutObjectRequest("your-bucket-name", fileName, bis, metadata);
        putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead);
        PutObjectResult putObjectResult = s3client.putObject(putObjectRequest);
        if (Objects.isNull(putObjectResult)) {
            throw new RuntimeException("文件上传失败");
        }
        return s3client.getUrl(bucketName, fileName).toString();
    }

    /**
     * 获取文件上传进度
     *
     * @param fileName 文件名称
     * @return 返回文件上传进度
     */
    @Override
    public FileUploadStatusVO getFileUploadPlan(String fileName, String bucketName) {
        throw new RuntimeException("暂不支持,如需使用，自行官网集成");
    }

    /**
     * 文件下载
     *
     * @param response 响应
     * @param fileName 文件名称
     */
    @Override
    public void fileDownload(HttpServletResponse response, String fileName, String bucketName) {
        InputStream inputStream = null;
        try {
            S3Object s3Object = s3client.getObject("your-bucket-name", fileName);
            inputStream = s3Object.getObjectContent();
            response.setContentType(s3Object.getObjectMetadata().getContentType());
            response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
            byte[] buffer = new byte[4096];
            int bytesRead = -1;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                response.getOutputStream().write(buffer, 0, bytesRead);
            }

        } catch (Exception e) {
            throw new RuntimeException("文件下载失败");
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            try {
                if (response.getOutputStream() != null) {
                    response.getOutputStream().flush();
                    response.getOutputStream().close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }

    /**
     * 删除文件
     *
     * @param fileName   文件名称
     * @param bucketName 桶名称
     */
    @Override
    public void deleteFile(String fileName, String bucketName) {
        s3client.deleteObject(bucketName, fileName);
    }
}
